﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace JSKE.DiaryAndTracking
{
    public class Element
    {
        public string Name { get; set; }
        public Double Percentage { get; set; }
        public Color Color { get; set; }
        public Element(string name, Double percentage, Color color)
        {
            Name = name;
            this.Percentage = percentage;
            Color = color;
        }
        public override string ToString()
        {
            return Name + " | " + Percentage + "%";
        }

    }

    public class PieChart
    {
        List<Element> elements = new List<Element>(5);
        Graphics objGraphics;
        Double sum = 0.0;

        public PieChart()
        {
            this.Depth = 10;
        }
        public PieChart(Graphics objGraphics)
        {
            this.objGraphics = objGraphics;
            this.Depth = 10;
        }
        public PieChart(Element[] elements)
        {
            this.Depth = 10;
            this.elements = new List<Element>(elements);

            foreach (Element element in elements)
                sum += element.Percentage;
        }
        public PieChart(Element[] elements, Graphics objGraphics)
        {
            this.Depth = 10;
            this.objGraphics = objGraphics;
            this.elements = new List<Element>(elements);

            foreach (Element element in elements)
                sum += element.Percentage;
        }

        public int FirstAngle
        {
            get;
            set;
        }
        public int Depth
        {
            get;
            set;
        }
        public void Add(Element element)
        {
            elements.Add(element);
            sum += element.Percentage;
        }
        public void Draw()
        {
            Draw(objGraphics);
        }
        public void Draw(Graphics objGraphics)
        {
            // thiết lập vị trí vẽ và kích thước biểu đồ
            // dựa trên không gian vẽ là objGraphics.

            int x = (int)objGraphics.VisibleClipBounds.Left + 5;
            int y = (int)objGraphics.VisibleClipBounds.Top + 5;
            int width = (int)objGraphics.VisibleClipBounds.Width - 10;
            int height = (int)objGraphics.VisibleClipBounds.Height - this.Depth - 10;

            // Thiết lập góc bắt đầu vẽ. 
            // mặc định là -90, vị trí 12h.

            Double startAngle = FirstAngle - 90;
            Double sweepAngle;
            SolidBrush objBrush = new SolidBrush(Color.Aqua);

            // bật chế dộ chống răng cưa.
            objGraphics.SmoothingMode = SmoothingMode.AntiAlias;

            // tạo bút vẽ với hiệu ứng bóng cho cảm giác ánh sáng.
            LinearGradientBrush lbrush = new LinearGradientBrush(new Point(x, y), 
                                                                    new Point(x + width, y), 
                                                                    Color.BlueViolet, Color.Black);
            ColorBlend cb = new ColorBlend(2);
            cb.Positions[0] = 0.0f;
            cb.Positions[1] = 1.0f;

            for (int i = 0; i < this.elements.Count; ++i)
            {
                // tính toán đọ rộng góc vẽ cho mỗi pie 
                // tương ứng với amount của element.
                if (i == this.elements.Count - 1)
                    sweepAngle = 360 - startAngle + FirstAngle - 90;
                else
                    sweepAngle = this.elements[i].Percentage * 360 / sum;

                objBrush.Color = this.elements[i].Color;

                cb.Colors[0] = ControlPaint.Light(objBrush.Color);
                cb.Colors[1] = ControlPaint.Dark(objBrush.Color, 0.05f);
                lbrush.InterpolationColors = cb;

                // vẽ hiệu ứng 3D khi góc vẽ của pie đi qua vị trí bên dưới,
                // từ 0* -> 180*
                if (0 < startAngle + sweepAngle && startAngle < 180)
                {
                    // tắt thiết lập chống răng cưa để nét vẽ di liền nhau.
                    objGraphics.SmoothingMode = SmoothingMode.HighSpeed;
                    Pen p = new Pen(ControlPaint.Dark(objBrush.Color, 0.05f));

                    Double begin = Math.Max(startAngle, 0);
                    Double sweep = Math.Min(startAngle + sweepAngle, 180) - begin;

                    // Vẽ liên tiếp các cung chồng lên nhau tạo cảm giác 3D.
                    float iLoop;
                    for (iLoop = 0; iLoop < this.Depth; ++iLoop)
                        objGraphics.DrawArc(p, (float)x, (float)y + iLoop, (float)width, 
                                            (float)height, (float)begin, (float)sweep);

                    // bật lại chống răng cưa và vẽ đường viền ngoài cùng
                    objGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                    p.Width = 2;
                    objGraphics.DrawArc(p, (float)x, (float)y + iLoop - 1, 
                                           (float)width, (float)height, 
                                           (float)begin, (float)sweep);
                }

                // tô màu vùng vừa vẽ.
                objGraphics.FillPie(lbrush, (float)x, (float)y, 
                                    (float)width, (float)height, 
                                    (float)startAngle, (float)sweepAngle);
                objGraphics.DrawArc(new Pen(objBrush, 2), (float)x, (float)y, 
                                    (float)width, (float)height, (float)startAngle, (float)sweepAngle);

                // tăng góc vẽ cho element kế tiếp
                startAngle += sweepAngle;
            }
        }
    }
}
